
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import com.herohead.*;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import redis.clients.jedis.Jedis;

/*
 * <savegroupname>
 * <savegroupstatus>
 * <starttime>
 * <endtime>
 * <restarttime>
 * <totalclient>
 * <clientlist>
 * <client>
 * <status>
 */

public class dailyreports {

	
	static Jedis jedis;
	
	public static String savegroupName;
	public static String startTime;
	public static String endTime;
	public static String restartTime;
	public static String[] succeeded;
	public static String[] failed;
	public static String[] disabled;
	public static String groupStatus;
	public static String totalClients;
	public static String clientStatus;

	private static String rabbitServer;
	private static String RMQVirtualHost;
	private static String RMQUsername;
	private static String RMQPassword;
	private static String RMQQueue;

	private static String totalLogsQueue;

	private static String toEmail;
	private static String fromEmail;

	private static int publishCount = 0;


	static PropertiesConfiguration config;
	private static org.apache.log4j.Logger log= Logger.getLogger(dailyreports.class);

	static Channel ch, ch2;

	@SuppressWarnings("deprecation")
	public static  void main(String[] args) throws IOException, ConfigurationException, Throwable {
		// TODO Auto-generated method stub

		//String className = this.getClass().getSimpleName();

		CDLogger l = new CDLogger();
		Misc m = new Misc();

		l.programStart(log);

		//log.info("Program starting");
		String className = "dailyreports";

		/*  
		 * Read in Configuration file.
		 */

		config = new PropertiesConfiguration(className + ".config");
		config.setAutoSave(true);

		String clientSearch = config.getString("clientSearch");
		rabbitServer = config.getString("rabbitmqserver");
		RMQVirtualHost = config.getString("RMQVirtualHost");
		RMQUsername = config.getString("RMQUsername");
		RMQPassword = config.getString("RMQPassword");
		RMQQueue = config.getString("RMQQueue");
		String system = config.getString("System");
		String sourceServer = config.getString("SourceServer");
		String backupLog = config.getString("backupLog");
		toEmail = config.getString("toEmail");
		fromEmail = config.getString("fromEmail");
		totalLogsQueue = config.getString("totalLogsQueue");




		toEmail = toEmail.replace(" " , ",");
		Rabbitmq rmq = new Rabbitmq();

		rmq.setHostname(rabbitServer);
		rmq.setLogin(RMQVirtualHost, RMQPassword, RMQUsername);

		ch = rmq.setupChannel();
		AMQP.BasicProperties properties = new AMQP.BasicProperties();
		properties.setDeliveryMode(2);
		boolean durable = true;
		ch.queueDeclare(RMQQueue, durable, false, false, null);

		//System.out.println(clientSearch);

		//Misc m = new Misc();

		//String sq = (m.readStdin());

		String fileInput = args[0];

		log.debug(fileInput);
		File file = new File(fileInput);
		//List lines = FileUtils.readLines(file, "UTF-8");
		String sq = FileUtils.readFileToString(file, "UTF-8");
		//log.debug(sq);
		String[] slist = sq.split("\n");

		NWsavegroup nwsg = new NWsavegroup();
		nwsg.loadVars(slist);
		startTime = NWsavegroup.startTime;
		endTime = NWsavegroup.endTime;
		savegroupName = NWsavegroup.savegroupName;
		groupStatus = NWsavegroup.groupStatus;
		restartTime = NWsavegroup.restartTime;
		failed = NWsavegroup.failed;
		disabled = NWsavegroup.disabled;
		succeeded = NWsavegroup.succeeded;

		nwsg.system = system;
		nwsg.sourceServer = sourceServer;

		String emailBody = null;

		log.debug(clientSearch);
		String[] cs = clientSearch.split(" ");
		//log.debug(sq);

		for (String strClient : cs ) {
			log.debug("Looking for client " + strClient);
			//System.out.println("Looking for client " + strClient);
			if (nwsg.checkIfExist(strClient)) {
				log.info("Found the following client " + strClient);
				clientStatus = nwsg.getClientStatus(strClient);
				try {
					emailBody = (nwsg.formatXML(system,sourceServer,savegroupName,groupStatus,startTime,endTime,restartTime,NWsavegroup.totalClients,nwsg.getSucceededString(),strClient,nwsg.getClientStatus(strClient),nwsg.getDetails(strClient)));
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				log.debug(emailBody);
				Xml x = new Xml();
				String xmlString = x.sendEmail(toEmail, fromEmail, strClient + " backup status " + clientStatus  + " group " + savegroupName, emailBody, "smtp.am.mt.mtnet");
				log.debug("I have removed the email piece from this program.... !!!!");
				//ch.basicPublish("", RMQQueue, properties, xmlString.getBytes());
				log.info("Send Messaage");
			}
		}

		/* 
		 * cycle through all the clients and send status
		 */

		log.debug("Getting ready to send all clients......!!!!!!!!");

		List<String> clientList  = nwsg.getClientList();

		String clientLog;

		ch2 = rmq.setupChannel();
		properties = new AMQP.BasicProperties();
		properties.setDeliveryMode(2);
		durable = true;
		ch2.queueDeclare(backupLog, durable, false, false, null);

		// redis setup
		
		String redisHost = "172.18.38.14";
		jedis = new Jedis(redisHost); 
		
		String groupAlert = "prod.nw.stats.group.alert";
		String groupNotice = "prod.nw.stats.group.notice";
		String groupGood = "prod.nw.stats.group.good";
		
		String serverFailure = "prod.nw.stats.server.failure";
		String serverFailureAlert = "prod.nw.alerts.servers.";
		int serverFailureTimeout = 86400;
		String serverNotice = "prod.nw.stats.server.notice";
		String serverGood = "prod.nw.stats.server.good";
		
		String serverAlert = "prod:backup-alerts:nw:eu:server#";
		String serverAlertSeq = "prod:backup-alerts-seq:nw:eu:server#";
		String serverFailureTimed = "prod:backup-failureTimed:nw:eu:server#";
		
		String serverBackupCount = "prod:backup-stats-seq:nw:eu";
		
		
		
		
		for (String strClient : clientList ) {
			clientStatus = nwsg.getClientStatus(strClient);
			log.debug(strClient);
			try {
				String[] sDetails = nwsg.getDetails(strClient).split("\n");
				String numFiles = nwsg.getNumfiles(sDetails);
				String size = String.valueOf(m.convertToBytes(nwsg.getSize(sDetails)));
				String backupType = nwsg.getBackupType(sDetails);
				String module = nwsg.getModule(sDetails); 

				clientLog = (formatXML(system,sourceServer,savegroupName,groupStatus,NWsavegroup.convertNWDateToTS(startTime),NWsavegroup.convertNWDateToTS(endTime),restartTime,NWsavegroup.getClientListStr(),NWsavegroup.totalClients,strClient,groupStatus,nwsg.getClientStatus(strClient),nwsg.getDetails(strClient),numFiles,size,"0","0","0",backupType));
				if (nwsg.getClientStatus(strClient).equals("Failed")) {
					updateRedisServer(serverFailure, strClient);
					Long i = jedis.setnx(serverFailureTimed + strClient + "#" + module , strClient + ":" + module);
					if (i == 1) {
						jedis.expire(serverFailureTimed + strClient + "#" + module,serverFailureTimeout);
					}
					//String alertSeqId = jedis.incr(serverAlertSeq + "strClient").toString();
					//jedis.setex(serverFailureAlert + strClient + "#" + alertSeqId, serverFailureTimeout, strClient);

					
				} else if (nwsg.getClientStatus(strClient).equals("Notice")) {
					updateRedisServer(serverNotice, strClient);
				} else {
					updateRedisServer(serverGood, strClient);
					jedis.del(serverFailureAlert + strClient, strClient);
				}
				
				//String id = jedis.incr("seq.backup.nw.stats.id").toString();
				
				//jedis.set("prod:backup-savegroup:eu:" + id + ":server#" + strClient, strClient);
				//jedis.set("prod:backup-savegroup:eu:" + id + ":module#" + module,module);

				jedis.incr(serverBackupCount);
				
				/*
				ch2 = rmq.setupChannel();
				properties = new AMQP.BasicProperties();
				properties.setDeliveryMode(2);
				durable = true;
				ch2.queueDeclare(backupLog, durable, false, false, null);
				 */
				ch2.basicPublish("", backupLog, properties, clientLog.getBytes());
				publishCount++;
				log.info(savegroupName + " " + strClient );

				//	System.out.println(clientLog);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			//			ch.basicPublish("", RMQQueue, properties, xmlString.getBytes());
			//			log.info("Send Messaage");

		}

		if (publishCount > 0 ) {
			Channel totals = rmq.setupChannel();
			//properties = new AMQP.BasicProperties();
			properties.setDeliveryMode(2);
			durable = true;
			totals.queueDeclare(totalLogsQueue, durable, false, false, null);
			/* sourceSystem = sourceSystem
			 * type = publish
			 * publichedCount = count
			 */


			String xml= formatTotalsXML(sourceServer,Integer.toString(publishCount),"published",Misc.getTimestamp());
			totals.basicPublish("", totalLogsQueue, properties, xml.getBytes());

			if (groupStatus.equals("Alert")) {
				updateRedisServer(groupAlert,savegroupName);
				
			} else if (groupStatus.equals("Notice")) {
				updateRedisServer(groupNotice ,savegroupName );
			} else 
				updateRedisServer(groupGood ,savegroupName );
		}




		//log.debug("I have removed the delete file from the program!!!!!");
		log.debug("I have removed the email piece from this program.... !!!!");
		//log.info("Program Finishing");
		file.delete();
		l.programStop(log);
		System.exit(0);
	}

	public static String formatXML(String system, String sourceSystem,String savegroupName, String groupStatus,String savegroupStartTime, String savegroupEndTime, String restartTime, String clientList, String totalClients, String client, String status, String clientStatus, String clientDetails,String numberOfFiles,String bytesScanned, String newBytes, String clientPerCentNew, String started_ts, String backupType ) throws TransformerException{

		/*
		 * aded groupstatus
		 * added restartTime
		 * added totalClients
		 * added clientStatus
		 * 
		 */

		String timeStamp = Misc.getTimestamp();
		try {
			DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

			// root elements
			Document doc = docBuilder.newDocument();
			Element rootElement = doc.createElement("savegrouplog");
			doc.appendChild(rootElement);
			Element e0 = doc.createElement("timestamp");
			e0.appendChild(doc.createTextNode(timeStamp));
			rootElement.appendChild(e0);
			Element es = doc.createElement("system");
			es.appendChild(doc.createTextNode(system));
			rootElement.appendChild(es);
			Element es1 = doc.createElement("sourceSystem");
			es1.appendChild(doc.createTextNode(sourceSystem));
			rootElement.appendChild(es1);
			Element e = doc.createElement("saveGroupName");
			e.appendChild(doc.createTextNode(savegroupName));
			rootElement.appendChild(e);
			Element e1 = doc.createElement("saveGroupStatus");
			e1.appendChild(doc.createTextNode(groupStatus));
			rootElement.appendChild(e1);
			Element e2 = doc.createElement("saveGroupStartTime");
			e2.appendChild(doc.createTextNode(savegroupStartTime));
			rootElement.appendChild(e2);
			Element e3 = doc.createElement("saveGroupEndTime");
			e3.appendChild(doc.createTextNode(savegroupEndTime));
			rootElement.appendChild(e3);
			Element e4 = doc.createElement("saveGroupRestartTime");
			e4.appendChild(doc.createTextNode(restartTime));
			rootElement.appendChild(e4);
			Element e5 = doc.createElement("saveGroupClientCount");
			e5.appendChild(doc.createTextNode(totalClients));
			rootElement.appendChild(e5);
			Element e5a = doc.createElement("saveGroupClientList");
			e5a.appendChild(doc.createTextNode(clientList));
			rootElement.appendChild(e5a);
			/*			Element e6 = doc.createElement("clientlist");
			e6.appendChild(doc.createTextNode(clientList));
			rootElement.appendChild(e6);
			 */			Element e7 = doc.createElement("clientName");
			 e7.appendChild(doc.createTextNode(client));
			 rootElement.appendChild(e7);
			 Element e8 = doc.createElement("clientStatus");
			 e8.appendChild(doc.createTextNode(clientStatus));
			 rootElement.appendChild(e8);
			 Element e9 = doc.createElement("clientDetails");
			 e9.appendChild(doc.createTextNode(clientDetails));
			 rootElement.appendChild(e9);
			 Element e9a = doc.createElement("clientFileCount");
			 e9a.appendChild(doc.createTextNode(numberOfFiles));
			 rootElement.appendChild(e9a);
			 Element e9a1 = doc.createElement("clientBytesScanned");
			 e9a1.appendChild(doc.createTextNode(bytesScanned));
			 rootElement.appendChild(e9a1);
			 Element e9a2 = doc.createElement("clientNewBytes");
			 e9a2.appendChild(doc.createTextNode(newBytes));
			 rootElement.appendChild(e9a2);
			 Element e9a3 = doc.createElement("clientPerCentNew");
			 e9a3.appendChild(doc.createTextNode(clientPerCentNew));
			 rootElement.appendChild(e9a3);
			 Element e9a4 = doc.createElement("started_ts");
			 e9a4.appendChild(doc.createTextNode(started_ts));
			 rootElement.appendChild(e9a4);
			 Element bT = doc.createElement("backupType");
			 bT.appendChild(doc.createTextNode(backupType));
			 rootElement.appendChild(bT);

			 TransformerFactory transformerFactory = TransformerFactory.newInstance();
			 Transformer transformer = transformerFactory.newTransformer();

			 DOMSource source = new DOMSource(doc);
			 StreamResult result = new StreamResult(new StringWriter());
			 transformer.transform(source, result);
			 //System.out.println(result.getWriter().toString());

			 return result.getWriter().toString();

		} catch (ParserConfigurationException pce) {
			pce.printStackTrace();
			return pce.toString();
		} catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return e.toString();
		}
	}
	public static String formatTotalsXML(String sourceSystem,String count, String type, String timestamp ) throws TransformerException{

		String timeStamp = Misc.getTimestamp();
		try {
			DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

			// root elements
			Document doc = docBuilder.newDocument();
			Element rootElement = doc.createElement("totals_log");
			doc.appendChild(rootElement);
			Element e0 = doc.createElement("sourceSystem");
			e0.appendChild(doc.createTextNode(sourceSystem));
			rootElement.appendChild(e0);
			Element es = doc.createElement("count");
			es.appendChild(doc.createTextNode(count));
			rootElement.appendChild(es);
			Element es1 = doc.createElement("type");
			es1.appendChild(doc.createTextNode(type));
			rootElement.appendChild(es1);
			Element est = doc.createElement("timestamp");
			est.appendChild(doc.createTextNode(timestamp));
			rootElement.appendChild(est);

			TransformerFactory transformerFactory = TransformerFactory.newInstance();
			Transformer transformer = transformerFactory.newTransformer();

			DOMSource source = new DOMSource(doc);
			StreamResult result = new StreamResult(new StringWriter());
			transformer.transform(source, result);
			//System.out.println(result.getWriter().toString());

			return result.getWriter().toString();

		} catch (ParserConfigurationException pce) {
			pce.printStackTrace();
			return pce.toString();
		} catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return e.toString();
		}
	}

	public static String checkNull(String s,boolean str) {
		if (s.length() == 0) 
			if (str) s = null;
			else s = "0";
		return s;
	}

	public static String removeMilli(String st) {
		if (st.indexOf(".") != -1) {
			return st.substring(0,st.indexOf("."));
		} else {
			return st;
		}

	}
	
	public static void updateRedisServer(String key, String client) {
		jedis.zincrby(key, 1, client);
	}

}


